//
// (C) Copyright 2014 Hiroyuki Tominaga, All Rights Reserved.
// code google: https://js-dragwindow.googlecode.com/svn/trunk/jquery.dragwindow.js
//
// demo: http://jsfiddle.net/motrohi/hu4nJ/
//
/*global jQuery */
if ( (window || self).jQuery ) {
    (function ($) {
        /* Strict mode for this plugin */
        "use strict";

		/* getActualScrollPosition */
		var _gasp;
        var jq_fn = $.fn;
        var _al = "addEventListener", _rl = "removeEventListener";
        /**
         * @param callback Specify callback function when you need debug.
         */
        jq_fn.dragWindow = function (capturePhaze, callback)
        {
            var _x = 0, _y = 0, _e, _id;
            //console.log(Manager);
            this.release = function() {
                this.reset();
                _removeListener();
                _e && _e[_rl]('mousedown', _mdown, true);
                Manager.remove(_e);
                _e = null;
                _id = "";
            };
            this.reset = function() {
                _x = 0, _y = 0;
            };
            this.setTarget = function(element) {
                this.release();
                _e = (element && typeof element !== "string")? element: null;
                try {
                    _id = (element && typeof element === "string")? element: element.id;
                } catch (e) {
                    console.log(e), _id = "";
                }
                _addListener(), Manager.add(_e);
                return this;
            };

            function logEvent(e) {
                if (!callback) return;
                callback(e);
            }

            /* If define as a prototype apparently a reference function seems to fail */
            /**
             * !!need implemented as closure function
             */
            function _addListener() {
                var target = _e;
                // lazy initiaize?.
                if (target === null) {
                    _e = target = document.getElementById(_id);
                }
                target[_al]('mousedown', _mdown, capturePhaze);
            };
            function _removeListener() {
                if (_e) {
                _e[_rl]('mousemove', _dragmove, capturePhaze);
                _e[_rl]('mouseup', _mup, capturePhaze);
                }
            };

            function _mdown(e) {
            	if (!e) e = window.event;
                logEvent(e);
                var target = e.target;
                if (target.id === _id) {
		            if (e.offsetX === undefined) { // firefox 対応.
		                var off = $(target).offset();
		                _x = e.pageX - off.left, _y = e.pageY - off.top;
		                //_x = e.layerX, _y = e.layerY;
		            } else {
		                _x = e.offsetX, _y = e.offsetY;
		            }
                    target[_al]('mousemove', _dragmove, capturePhaze);
                    target[_al]('mouseup', _mup, capturePhaze);
                    Manager.mostTop(target);
                    e.preventDefault();
                }
            };
            function _dragmove(e) {
        		if (!e) e = window.event;
                logEvent(e);
                var ss = _e.style, wsp = _gasp();
                ss.position = 'absolute';
                ss.top = e.clientY - _y + wsp.scrollY + 'px';
                ss.left = e.clientX - _x + wsp.scrollX + 'px';
                //console.log(e.type);
                e.preventDefault();
            };
            function _mup(e) {
        		if (!e) e = window.event;
                logEvent(e);
                _removeListener(), e.preventDefault();
            };

            capturePhaze === undefined && (capturePhaze = false);
            return this.setTarget(this[0]);
        }; // ---------------------------------- dragWindow

        /* singleton */
        var Manager = {
            lock: false,
            elements: [],
            add: function(element) {
                if (element && !this.lock)
                    this.elements.push(element);
            },
            remove: function(element) {
                if (element && !this.lock) {
                    this.lock = true;
                    var arry = this.elements, found;
                    for (var i in arry) {
                        if (arry[i] === element) {
                            arry[i] = undefined, found = true;
                            break; // "," での記述は NG
                        }
                    }
                    if (found) {
                        var new_arry = new Array(arry.length - 1), idx = 0;
                        for (var i in arry) {
                            arry[i] && (new_arry[idx++] = arry[i]);
                        }
                        this.elements = new_arry;
                    }
                    this.lock = false;
                }
            },
            mostTop: function(element) {
                if (element && !this.lock) {
                    this.lock = true;
                    var arry = this.elements, max = 0, zIndex = 0;
                    for (var i in arry) {
                        var e = arry[i];
                        /* if (e.parentNode === null) {
							this.lock = false, this.remove(e), this.lock = true;
							continue;
                        }*/
                        if (e !== element) {
                            zIndex = parseInt(e.style.zIndex);
                            isNaN(zIndex) && (zIndex = 0), zIndex > max && (max = zIndex);
                        }
                    }
                    var zIndex2 = parseInt(element.style.zIndex);
                    isNaN(zIndex2) && (zIndex2 = 0), zIndex2 <= max && (element.style.zIndex = max + 1);
                    this.lock = false;
                }
            }
        }; // ------------------------- Manager

		// from :https://developer.mozilla.org/ja/docs/Web/API/window.scrollY
		_gasp = window.getActualScrollPosition || $.gasp || function gasp() {
			var x = (window.pageXOffset !== undefined)?
				window.pageXOffset: (document.documentElement || document.body.parentNode || document.body).scrollLeft,
			y = (window.pageYOffset !== undefined)?
				window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
			return { scrollX: x, scrollY: y };
		};

    })( (window || self).jQuery );

} // ------ if (jQuery)


